package com.cocos.game;

import static com.cocos.lib.GlobalObject.runOnUiThread;

import android.content.Context;
import android.net.Uri;
import android.os.Handler;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

import androidx.annotation.NonNull;

import com.adjust.sdk.Adjust;
import com.adjust.sdk.AdjustAdRevenue;
import com.applovin.mediation.MaxAd;
import com.applovin.mediation.MaxAdFormat;
import com.applovin.mediation.MaxAdListener;
import com.applovin.mediation.MaxAdViewAdListener;
import com.applovin.mediation.MaxAdViewConfiguration;
import com.applovin.mediation.MaxError;
import com.applovin.mediation.MaxReward;
import com.applovin.mediation.MaxRewardedAdListener;
import com.applovin.mediation.ads.MaxAdView;
import com.applovin.mediation.ads.MaxInterstitialAd;
import com.applovin.mediation.ads.MaxRewardedAd;
import com.applovin.sdk.AppLovinMediationProvider;
import com.applovin.sdk.AppLovinSdk;
import com.applovin.sdk.AppLovinSdkConfiguration;
import com.applovin.sdk.AppLovinSdkInitializationConfiguration;
import com.applovin.sdk.AppLovinSdkSettings;
import com.applovin.sdk.AppLovinSdkUtils;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.concurrent.TimeUnit;

import classic.card.fun.casual.solitaire.game.patience.R;

public class ApplovinHelper {
    public static ApplovinHelper instance;
    public AppActivity context;
    public static void init() {
        instance = new ApplovinHelper();
        instance.context = AppActivity.act;
        instance.initSDK();
    }
    public void initSDK() {
        Log.d(TAG, "initSDK: ");
        
        AppLovinSdkSettings settings = AppLovinSdk.getInstance( context ).getSettings();
        settings.getTermsAndPrivacyPolicyFlowSettings().setEnabled( true );
        settings.getTermsAndPrivacyPolicyFlowSettings().setPrivacyPolicyUri( Uri.parse( "https://www.startnewgames.com/privacy_policy.html" ) );

        // Terms of Service URL is optional
        settings.getTermsAndPrivacyPolicyFlowSettings().setTermsOfServiceUri( Uri.parse( "https://www.startnewgames.com/terms_of_service.html" ) );
        // Showing Terms & Privacy Policy flow in GDPR region is optional (disabled by default)
        settings.getTermsAndPrivacyPolicyFlowSettings().setShowTermsAndPrivacyPolicyAlertInGdpr( true );

        if(JsbHelper.ENV_TYPE == 0) {
            testGDPR();
        }
// Create the initialization configuration
        AppLovinSdkInitializationConfiguration initConfig = AppLovinSdkInitializationConfiguration.builder( context.getString(R.string.applovin_key), context )
                .setMediationProvider( AppLovinMediationProvider.MAX )
                .build();
        // Initialize the SDK with the configuration
        AppLovinSdk.getInstance( context ).initialize( initConfig, new AppLovinSdk.SdkInitializationListener()
        {
            @Override
            public void onSdkInitialized(final AppLovinSdkConfiguration sdkConfig)
            {
                Log.d(TAG, "onSdkInitialized: ");
                // Start loading ads
                instance.createBannerAd();
                instance.createInterstitialAd();
                instance.createRewardedAd();
                // if (JsbHelper.ENV_TYPE == 0) {
                //     AppLovinSdk.getInstance( context ).showMediationDebugger();
                // }
            }
        } );
    }
    private MaxInterstitialAd interstitialAd;

    private MaxAdView bannerAd;
    private String bannerAdPlacement = "";

    public void showAd(int adType, String placement, String customData, String change) {
        // 先判断广告是否加载
        boolean bReady1 = interstitialAd.isReady();
        boolean bReady2 = rewardedAd.isReady();
        if (adType == 1 && !bReady1 && bReady2) {
            changeAdType1(adType);
            adType = 2;
        } else if (adType == 2 && bReady1 && !bReady2) {
            changeAdType1(adType);
            adType = 1;
        } else if ("1".equals(change)) {
            adType = changeAdType(adType);
        }
        if (adType == 1) {
            showInterstitialAd(placement, customData);
        } else {
            showRewardedAd(placement, customData);
        }
    }
    public void showInterstitialAd(String placement, String customData) {
        if ( interstitialAd.isReady() ) {
            interstitialAd.showAd( placement, customData, context);
        } else {
            JsbHelper.emit("respShowAdInter", "0");
        }
    }
    public void showRewardedAd(String placement, String customData) {
        if ( rewardedAd.isReady() ) {
            rewardedAd.showAd( placement, customData, context);
        } else {
            JsbHelper.emit("respShowAdRewarded", "0");
        }
    }
    public void showBanner(String placement, String customData) {
        bannerAdPlacement = placement;
        bannerAd.setPlacement(placement);
        bannerAd.setCustomData(customData);
        bannerAd.startAutoRefresh();
        bannerAd.setExtraParameter("ad_refresh_seconds", "15");
        runOnUiThread(() -> {
            bannerAd.setVisibility(View.VISIBLE);
//            bannerAd.setExtraParameter("adaptive_banner", "true");
        });
    }
    public void hideBanner() {
        if (bannerAd == null) {
            return;
        }
        bannerAd.stopAutoRefresh();
        runOnUiThread(() -> {
            bannerAd.setVisibility(View.GONE);
        });
    }
    public void setUserID(String userID) {
        AppLovinSdkSettings settings = AppLovinSdk.getInstance( AppActivity.act ).getSettings();
        settings.setUserIdentifier( userID );
//        settings.setExtraParameter( "uid2_token", "«token-value»" );
    }
    public void createBannerAd() {
        int width = ViewGroup.LayoutParams.MATCH_PARENT;
        int heightDp = MaxAdFormat.BANNER.getAdaptiveSize( context ).getHeight();
        int heightPx = AppLovinSdkUtils.dpToPx( context, heightDp );
        MaxAdViewConfiguration config = MaxAdViewConfiguration.builder()
                .setAdaptiveType( MaxAdViewConfiguration.AdaptiveType.ANCHORED )
                .build();
        bannerAd = new MaxAdView("b15237c038ba13a5", config);
        bannerAd.setLayoutParams( new FrameLayout.LayoutParams( width, heightPx, Gravity.BOTTOM) );
        FrameLayout rootView = context.findViewById(android.R.id.content);
        rootView.addView(bannerAd);
        bannerAd.setVisibility(View.GONE);
        bannerAd.setListener(new MaxAdViewAdListener() {
            int retryAttempt = 0;
            @Override
            public void onAdExpanded(@NonNull MaxAd maxAd) {
                Log.d(TAG, "banner onAdExpanded: ");
            }
            @Override
            public void onAdCollapsed(@NonNull MaxAd maxAd) {
                Log.d(TAG, "banner onAdCollapsed: ");
            }
            @Override
            public void onAdLoaded(@NonNull MaxAd maxAd) {
                Log.d(TAG, "banner onAdLoaded: ");
                retryAttempt = 0;
                JsbHelper.emit("respAdLoadBanner", createAdParamJson(maxAd));
            }
            @Override
            public void onAdDisplayed(@NonNull MaxAd maxAd) {
                Log.d(TAG, "banner onAdDisplayed: ");
            }
            @Override
            public void onAdHidden(@NonNull MaxAd maxAd) {
                Log.d(TAG, "banner onAdHidden: ");
            }
            @Override
            public void onAdClicked(@NonNull MaxAd maxAd) {
                Log.d(TAG, "banner onAdClicked: ");
                JsbHelper.emit("respAdClicked", "3");
            }

            @Override
            public void onAdLoadFailed(@NonNull String s, @NonNull MaxError maxError) {
                Log.d(TAG, "banner onAdLoadFailed: ");
                retryAttempt++;
                if (retryAttempt > 3) {
                    JsbHelper.emit("respAdLoadFaildBanner", s);
                    return;
                }
                long delayMillis = TimeUnit.SECONDS.toMillis( (long) Math.pow( 2, Math.min( 6, retryAttempt ) ) );
                new Handler().postDelayed(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        bannerAd.loadAd();
                    }
                }, delayMillis );
            }
            @Override
            public void onAdDisplayFailed(@NonNull MaxAd maxAd, @NonNull MaxError maxError) {
                Log.d(TAG, "banner onAdDisplayFailed: ");
            }
        });
        bannerAd.setRevenueListener(maxAd -> {
            Log.d(TAG, "trackAdRevenue bannerAd");
            AdjustAdRevenue adjustAdRevenue = new AdjustAdRevenue("applovin_max_sdk");
            adjustAdRevenue.setRevenue(maxAd.getRevenue(), "USD");
            adjustAdRevenue.setAdRevenueNetwork(maxAd.getNetworkName());
            adjustAdRevenue.setAdRevenueUnit(maxAd.getAdUnitId());
            adjustAdRevenue.setAdRevenuePlacement(maxAd.getPlacement());
            Adjust.trackAdRevenue(adjustAdRevenue);
            FirebaseHelper.adEvent(maxAd);
        });
    }
    public void loadBanner() {
        bannerAd.loadAd();
    }
    public void createInterstitialAd() {
        interstitialAd = new MaxInterstitialAd( "e826b54c0daee6e8", context.getApplicationContext() );
        interstitialAd.setListener(new MaxAdListener() {
            int retryAttempt = 0;
            @Override
            public void onAdLoaded(@NonNull MaxAd maxAd) {
                Log.d(TAG, "inter onAdLoaded eCPM: " + maxAd.getRevenue() * 1000);
                adEcpmInter = maxAd.getRevenue() * 1000;
                adTypeEcpm = adEcpmRewarded >= adEcpmInter * 1.1 ? 2 : 1;
                Log.d(TAG, "adTypeEcpm: " + adTypeEcpm);
                retryAttempt = 0;
                JsbHelper.emit("respAdLoadInter", createAdParamJson(maxAd));
            }
            @Override
            public void onAdDisplayed(@NonNull MaxAd maxAd) {
                Log.d(TAG, "inter onAdDisplayed: ");
                JsbHelper.emit("respShowAdInter", "1");
            }
            @Override
            public void onAdHidden(@NonNull MaxAd maxAd) {
                Log.d(TAG, "inter onAdHidden: ");
                interstitialAd.loadAd(); // Interstitial ad is hidden. Pre-load the next ad
            }
            @Override
            public void onAdClicked(@NonNull MaxAd maxAd) {
                Log.d(TAG, "inter onAdClicked: ");
                JsbHelper.emit("respAdClicked", "1");
            }
            @Override
            public void onAdLoadFailed(@NonNull String s, @NonNull MaxError maxError) {
                Log.d(TAG, "inter onAdLoadFailed: ");
                retryAttempt++;
                if (retryAttempt > 3) {
                    JsbHelper.emit("respAdLoadFaildInter", s);
                    return;
                }
                long delayMillis = TimeUnit.SECONDS.toMillis( (long) Math.pow( 2, Math.min( 6, retryAttempt ) ) );
                new Handler().postDelayed(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        interstitialAd.loadAd();
                    }
                }, delayMillis );
            }
            @Override
            public void onAdDisplayFailed(@NonNull MaxAd maxAd, @NonNull MaxError maxError) {
                Log.d(TAG, "inter onAdDisplayFailed: ");
                interstitialAd.loadAd();
                JsbHelper.emit("respShowAdInter", "0");
            }
        });
        interstitialAd.setRevenueListener(maxAd -> {
            Log.d(TAG, "trackAdRevenue interstitialAd");
            AdjustAdRevenue adjustAdRevenue = new AdjustAdRevenue("applovin_max_sdk");
            adjustAdRevenue.setRevenue(maxAd.getRevenue(), "USD");
            adjustAdRevenue.setAdRevenueNetwork(maxAd.getNetworkName());
            adjustAdRevenue.setAdRevenueUnit(maxAd.getAdUnitId());
            adjustAdRevenue.setAdRevenuePlacement(maxAd.getPlacement());
            Adjust.trackAdRevenue(adjustAdRevenue);
            FirebaseHelper.adEvent(maxAd);
        });
//        loadInter();
    }
    public void loadInter() {
        interstitialAd.loadAd();
    }
    private MaxRewardedAd rewardedAd;

    void createRewardedAd()
    {
        rewardedAd = MaxRewardedAd.getInstance( "0ef02a76df6d76b1", context.getApplicationContext() );
        rewardedAd.setListener(new MaxRewardedAdListener() {
            int retryAttempt = 0;
            @Override
            public void onUserRewarded(@NonNull MaxAd maxAd, @NonNull MaxReward maxReward) {
                Log.d(TAG, "rewarded onUserRewarded: ");
                // 发放奖励
                JsbHelper.emit("respAdRewarded", "1");
            }
            @Override
            public void onAdLoaded(@NonNull MaxAd maxAd) {
                Log.d(TAG, "rewarded onAdLoaded eCPM: " + maxAd.getRevenue() * 1000);
                adEcpmRewarded = maxAd.getRevenue() * 1000;
                adTypeEcpm = adEcpmInter >= adEcpmRewarded * 1.1 ? 1 : 2;
                Log.d(TAG, "adTypeEcpm: " + adTypeEcpm);
                retryAttempt = 0;
                JsbHelper.emit("respAdLoadRewarded", createAdParamJson(maxAd));
            }
            @Override
            public void onAdDisplayed(@NonNull MaxAd maxAd) {
                Log.d(TAG, "rewarded onAdDisplayed: ");
                JsbHelper.emit("respShowAdRewarded", "1");
            }
            @Override
            public void onAdHidden(@NonNull MaxAd maxAd) {
                Log.d(TAG, "rewarded onAdHidden: ");
                rewardedAd.loadAd();
            }
            @Override
            public void onAdClicked(@NonNull MaxAd maxAd) {
                Log.d(TAG, "rewarded onAdClicked: ");
                JsbHelper.emit("respAdClicked", "2");
            }
            @Override
            public void onAdLoadFailed(@NonNull String s, @NonNull MaxError maxError) {
                Log.d(TAG, "rewarded onAdLoadFailed: ");
                retryAttempt++;
                if (retryAttempt > 3) {
                    JsbHelper.emit("respAdLoadFaildRewarded", s);
                    return;
                }
                long delayMillis = TimeUnit.SECONDS.toMillis( (long) Math.pow( 2, Math.min( 6, retryAttempt ) ) );
                new Handler().postDelayed(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        rewardedAd.loadAd();
                    }
                }, delayMillis );
            }
            @Override
            public void onAdDisplayFailed(@NonNull MaxAd maxAd, @NonNull MaxError maxError) {
                Log.d(TAG, "rewarded onAdDisplayFailed: ");
                rewardedAd.loadAd();
                JsbHelper.emit("respShowAdRewarded", "0");
                JsbHelper.emit("respAdRewarded", "0");
            }
        });
        rewardedAd.setRevenueListener(maxAd -> {
            Log.d(TAG, "trackAdRevenue rewardedAd");
            AdjustAdRevenue adjustAdRevenue = new AdjustAdRevenue("applovin_max_sdk");
            adjustAdRevenue.setRevenue(maxAd.getRevenue(), "USD");
            adjustAdRevenue.setAdRevenueNetwork(maxAd.getNetworkName());
            adjustAdRevenue.setAdRevenueUnit(maxAd.getAdUnitId());
            adjustAdRevenue.setAdRevenuePlacement(maxAd.getPlacement());
            Adjust.trackAdRevenue(adjustAdRevenue);
            FirebaseHelper.adEvent(maxAd);
        });
//        loadRewarded();
    }
    public void loadRewarded() {
        rewardedAd.loadAd();
    }
    public static final String TAG = "xxxjs";

//    public int adTypeCur = 0;
    public int adTypeEcpm = 0;
    public double adEcpmInter = 0;
    public double adEcpmRewarded = 0;
    /**
     * 替换为更高eCPM的广告
     * @param adType 1插屏 2激励
     * @return
     */
    public int changeAdType(int adType) {
        Log.d(TAG, "changeAdType: " + adType);
        if (adTypeEcpm != 0 && adType != adTypeEcpm) {
            double preEcpm = Math.min(adEcpmInter, adEcpmRewarded);
            double curEcpm = Math.max(adEcpmInter, adEcpmRewarded);
            Log.d(TAG, "高价值广告替换 " + adType + " " + preEcpm + " " + adTypeEcpm + " " + curEcpm);
            try {
                JSONObject jo = new JSONObject();
                jo.put("ecpmBefore", preEcpm);
                jo.put("ecpmAfter", curEcpm);
                jo.put("adTypeBefore", adType2Str(adType));
                jo.put("adTypeAfter", adType2Str(adTypeEcpm));
                jo.put("reason", "highValue");
                JsbHelper.emit("respAdTypeChange", jo.toString());
            } catch (Exception e) {
                e.printStackTrace();
            }
//            BlossomUtil.sendToTs("adTypeChange", preEcpm, curEcpm,
//                    adType), adTypeEcpm, "highValue");
            return adTypeEcpm;
        } else {
            return adType;
        }
    }
    public void changeAdType1(int adType) {
        Log.d(TAG, "changeAdType: " + adType);
//        double preEcpm = Math.min(adEcpmInter, adEcpmRewarded);
//        double curEcpm = Math.max(adEcpmInter, adEcpmRewarded);
        double curEcpm = adType == 1? adEcpmInter : adEcpmRewarded;
        Log.d(TAG, "广告无填充替换 " + adType + " " + 0 + " "  + curEcpm);
        try {
            JSONObject jo = new JSONObject();
            jo.put("ecpmBefore", 0);
            jo.put("ecpmAfter", curEcpm);
            jo.put("adTypeBefore", adType2Str(adType));
            jo.put("adTypeAfter", adType2Str(adType % 2) + 1);
            jo.put("reason", "unfilled");
            JsbHelper.emit("respAdTypeChange", jo.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private String adType2Str(int adType) {
        if (adType == 1) {
            return "interstitial";
        }
        if (adType == 2) {
            return "rewarded";
        }
        if (adType == 3) {
            return "banner";
        }
        return "unknown";
    }

    private String createAdParamJson(MaxAd maxAd) {
        JSONObject object = new JSONObject();
        try {
            object.put("adunit_format", maxAd.getFormat().getLabel());
            object.put("adunit_id", maxAd.getAdUnitId());
            object.put("network_name", maxAd.getNetworkName());
            object.put("revenue", maxAd.getRevenue());
        } catch (JSONException e) {
            throw new RuntimeException(e);
        }
        return object.toString();
    }

    private void testGDPR() {
        AppLovinSdkSettings settings = AppLovinSdk.getInstance( context ).getSettings();
        settings.getTermsAndPrivacyPolicyFlowSettings().setDebugUserGeography( AppLovinSdkConfiguration.ConsentFlowUserGeography.GDPR );
        settings.setExtraParameter("google_test_device_hashed_id", JsbHelper.getDeviceId(context));
    }
}